/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _VAR_CACHE_H_
#define _VAR_CACHE_H_

#include "napi/native_api.h"
#include <map>
#include <list>
#include <string>
#include "assert/__assert.h"
#include "comm/thread/spinlock.h"

class VarCache {
  public:
    static VarCache* Singleton();
    
    virtual ~VarCache();

    napi_env GetJSEnv() 
    {
    	return jsenv_;
    }

    void SetJSEnv(napi_env jsenv)
    {
        ASSERT(jsenv);
        jsenv_ =jsenv;
    }

    static int FindProperties(napi_value klass_or_instance, std::map<std::string, napi_value>& property_map);
    static napi_value GetOnePropertyOfClass(const std::map<std::string, napi_value>& property_map, const char* property_name);
        
    int RegisterClass(const std::string& class_path, napi_value klass);
		
    std::map<std::string, napi_value>* GetClassProperties(const char* class_path);
    	
    napi_value GetOnePropertyOfClass(const std::string& class_path, const std::string& property_name);
    static napi_value GetOnePropertyOfObj(napi_value obj, const char* property_name);
    
    napi_value GetOneClass(const char* class_path);
    
    
    static void GetStaticPropertyId(const char* const class_path,
                             		   const char* const property_name, 
                             		   std::string& property_id);
    static void GetPropertyId(napi_value obj,
                                                        const char* const class_path,
                                                        const char* const property_name,
                                                        std::string& property_id);

  private:
    VarCache();
    
  private:
    napi_env jsenv_;
    std::map<std::string, std::map<std::string, napi_value>> class_property_map_;
    std::map<std::string, napi_ref> class_map_;
    SpinLock class_map_lock_;
};


EXTERN_C_START
napi_value AddClass(napi_env env, napi_callback_info info);
EXTERN_C_END

#ifdef __GNUC__
#define VARIABLE_IS_NOT_USED __attribute__ ((unused))
#else
#define VARIABLE_IS_NOT_USED
#endif

#define MAX_PROPERTY_NAME_SIZE 1000

int GetNAPIStringValue(napi_env env, napi_value arg, std::string& str);
int GetNAPIStringValue(napi_env env, napi_value arg, std::string* str);
bool AddClass(const char* const classPath);

/*
#define DEFINE_FIND_CLASS(classname, classpath) \
    VARIABLE_IS_NOT_USED static bool b_##classname = AddClass(classpath);\
    VARIABLE_IS_NOT_USED static const char* classname = classpath;


bool LoadStaticMethod(JNIEnv* env);
bool AddStaticMethod(const char* const _classname, const char* const _methodname, const char* const _methodsig);

bool LoadMethod(JNIEnv* env);
bool AddMethod(const char* const _classname, const char* const _methodname, const char* const _methodsig);

#define DEFINE_FIND_STATIC_METHOD(methodid, classname, methodname, methodsig) \
    VARIABLE_IS_NOT_USED static bool b_static_##methodid = AddStaticMethod(classname, methodname, methodsig);\
    VARIABLE_IS_NOT_USED const static JniMethodInfo methodid = JniMethodInfo(classname, methodname, methodsig);

#define DEFINE_FIND_METHOD(methodid, classname, methodname, methodsig) \
    VARIABLE_IS_NOT_USED static bool b_##methodid = AddMethod(classname, methodname, methodsig);\
    VARIABLE_IS_NOT_USED const static JniMethodInfo methodid = JniMethodInfo(classname, methodname, methodsig);


*/
#endif

